package com.answer.service.manager;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.answer.common.ErrorCode;
import com.answer.config.AiConfig;
import com.answer.exception.BusinessException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 通用 AI 调用能力
 */
@Component
public class AiManager {

    // 稳定的随机数
    private static final float STABLE_TEMPERATURE = 0.05f;

    /**
     * 执行同步稳定请求
     * 此方法通过调用doRequest方法，发送一个具有稳定温度设置的请求
     * 主要用于需要稳定温度参数的同步通信场景
     *
     * @param systemMessage 系统消息，用于传达系统级别的信息或指令
     * @param userMessage 用户消息，包含用户的具体请求或数据
     * @return 返回请求的响应结果
     */
    public String doSyncStableRequest(String systemMessage, String userMessage) {
        return doRequest(systemMessage, userMessage, STABLE_TEMPERATURE);
    }

    /**
     * 同步请求处理
     *
     * @param systemMessage 系统消息，用于传达系统级别的信息或指令
     * @param userMessage 用户消息，包含用户的具体请求或问题
     * @param temperature 温度参数，用于调节响应的随机性或创造性
     * @return 返回处理请求后生成的响应
     *
     * 此方法提供了一个同步的请求处理机制，通过接收系统消息、用户消息和温度参数，
     * 来生成或检索相应的响应。它是实现与外部系统或用户交互的核心环节。
     */
    public String doSyncRequest(String systemMessage, String userMessage, Float temperature) {
        return doRequest(systemMessage, userMessage, temperature);
    }

    /**
     * 构建并发送聊天请求
     * 该方法根据传入的系统消息、用户消息以及温度参数，构建一个聊天消息列表，
     * 并通过调用doRequest方法发送这个聊天消息列表
     *
     * @param systemMessage 系统消息的内容，用于提供上下文信息
     * @param userMessage 用户消息的内容，代表用户的查询或请求
     * @param temperature 生成回复时的随机性参数，控制生成结果的多样性
     * @return 从doRequest方法返回的响应结果
     */
    public String doRequest(String systemMessage, String userMessage, Float temperature) {
        // 创建一个聊天消息列表，用于存储即将发送的聊天消息
        List<Message> chatMessageList = new ArrayList<>();

        // 构建系统消息对象，并添加到聊天消息列表中
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content(systemMessage)
                .build();
        chatMessageList.add(systemMsg);

        // 构建用户消息对象，并添加到聊天消息列表中
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content(userMessage)
                .build();
        chatMessageList.add(userMsg);

        // 调用doRequest方法，传入聊天消息列表和温度参数，返回响应结果
        return doRequest(chatMessageList, temperature);
    }

    /**
     * 执行请求以生成文本
     *
     * @param messages 对话消息列表，用于构建请求的上下文
     * @param temperature 生成过程中的随机性控制参数，较高温度导致结果更加随机
     * @return 生成的文本内容
     * @throws BusinessException 如果生成过程中发生错误，则抛出业务异常
     */
    public String doRequest(List<Message> messages, Float temperature) {
        // 构建请求参数
        GenerationParam param = GenerationParam.builder()
                .model("qwen1.5-1.8b-chat") // 指定使用的模型
                .messages(messages) // 设置对话消息列表
                .resultFormat(GenerationParam.ResultFormat.MESSAGE) // 设置结果格式为消息
                .topP(0.8) // 设置topP参数，控制生成内容的多样性
                .temperature(temperature) // 使用传入的温度参数
                .build();
        try {
            // 调用生成函数执行请求
            GenerationResult result = callGenerationWithMessages(param);
            // 返回生成的文本内容
            return result.getOutput().getChoices().get(0).getMessage().getContent();
        } catch (Exception e) {
            // 异常处理：打印错误信息并抛出业务异常
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 根据提供的参数调用消息生成接口
     *
     * @param param 生成任务的参数对象，包含输入文本、配置等
     * @return 生成的结果，包含生成的文本和其他元数据
     * @throws ApiException 当API调用出错时抛出
     * @throws NoApiKeyException 当API密钥未设置时抛出
     * @throws InputRequiredException 当输入参数缺失时抛出
     */
    public static GenerationResult callGenerationWithMessages(GenerationParam param) throws ApiException, NoApiKeyException, InputRequiredException {
        AiConfig aiConfig = new AiConfig(); // 实例化AI配置类，用于获取生成实例
        Generation gen = aiConfig.getGeneration(); // 通过AI配置获取生成实例，此方法可能包含更多的配置信息
        return gen.call(param); // 调用生成实例的call方法，传入参数并返回生成结果
    }
}

